package com.example.websocket.websocket;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.websocket.entity.GroupMessage;
import com.example.websocket.entity.User;
import com.example.websocket.service.IGroupMessageService;
import com.example.websocket.service.IUserService;
import com.example.websocket.service.impl.GroupMessageServiceImpl;
import com.example.websocket.service.impl.GroupServiceImpl;
import com.example.websocket.service.impl.UserServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;

import java.util.concurrent.CopyOnWriteArraySet;

@Slf4j
@Component
@ServerEndpoint("/websocket/{groupid}/{userid}")
public class WebSocketController {

    static IUserService userService;

    @Autowired
    public void setUserService(IUserService userService){
        WebSocketController.userService = userService;
    }

    static IGroupMessageService groupMessageService;

    @Autowired
    public void setGroupMessageService(IGroupMessageService groupMessageService){
        WebSocketController.groupMessageService = groupMessageService;
    }


    private WebSocket webSocket;

    private static CopyOnWriteArraySet<WebSocket> clients = new CopyOnWriteArraySet<>();


    /**
     * OnOpen 表示有浏览器链接过来的时候被调用
     * OnClose 表示浏览器发出关闭请求的时候被调用
     * OnMessage 表示浏览器发消息的时候被调用
     * OnError 表示有错误发生，比如网络断开了等等
     */

    /**
     * 建立连接
     *
     * @param session
     */

    @OnOpen
    public void onOpen( Session session,@PathParam("groupid") String groupidd,@PathParam("userid") String useridd)  throws Exception {
        int userid = Integer.parseInt(useridd);
        User user = userService.selectByPrimaryKey(userid);

        int groupid = Integer.parseInt(groupidd);
        log.info("现在来连接的客户id：" + session.getId() + "用户名：" + user.getUsername());
        webSocket = new WebSocket();
        webSocket.setSession(session);
        webSocket.setGroupid(groupid);
        webSocket.setUserid(userid);
        clients.add(webSocket);
        log.info("有新连接加入！ 当前在线人数" + onlineNumber(groupid));
        try {

            //messageType 1代表上线 2代表下线 3代表在线名单 4代表普通消息
            //先给所有人发送通知，说我上线了
            Map<String, Object> map1 = new HashMap<>();
            map1.put("messageType", 1);
            map1.put("username", user.getUsername());
            sendMessageAllByGroupid(JSON.toJSONString(map1), groupid);


            //给自己发一条消息：告诉自己现在都有谁在线
            Map<String, Object> map2 = new HashMap<>();
            map2.put("messageType", 3);
            //移除掉自己
            List<String> userList = getOnlineUserList(groupid);
            map2.put("onlineUsers", userList);
            sendMessageTo(JSON.toJSONString(map2), userid);
        } catch (IOException e) {
            log.info(user.getUsername() + "上线的时候通知所有人发生了错误");
        }
    }



    @OnError
    public void onError(Session session, Throwable error) {
        log.info("服务端发生了错误" + error.getMessage());
        error.printStackTrace();
    }

    /**
     * 连接关闭
     */
    @OnClose
    public void onClose() {
        log.info("有连接关闭！id为：" + this.webSocket.getSession().getId());
        clients.remove(this.webSocket);
        try {
            //messageType 1代表上线 2代表下线 3代表在线名单  4代表普通消息
            Map<String, Object> map1 = new HashMap<>();
            map1.put("messageType", 2);
            map1.put("username", userService.selectByPrimaryKey(webSocket.getUserid()).getUsername());
            sendMessageAllByGroupid(JSON.toJSONString(map1), webSocket.getGroupid());
        } catch (IOException e) {
            log.info(webSocket.getUserid() + "下线的时候通知所有人发生了错误");
        }
        log.info("有连接关闭！ 当前在线人数" + onlineNumber(webSocket.getGroupid()));
    }

    /**
     * 收到客户端的消息
     *
     * @param message 消息
     * @param session 会话
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        try {
            log.info("来自客户端消息：" + message + "客户端的id是：" + session.getId());
            JSONObject jsonObject = JSON.parseObject(message);
            String textMessage = jsonObject.getString("messageData");
            int userid = jsonObject.getIntValue("userid");
            User user = userService.selectByPrimaryKey(userid);
            int groupid = jsonObject.getIntValue("groupid");
            //messageType 1代表上线 2代表下线 3代表在线名单  4代表普通消息
            Map<String, Object> map1 = new HashMap<>();
            map1.put("messageType", 4);
            map1.put("textMessage", textMessage);
            map1.put("username", user.getUsername());
            GroupMessage groupMessage = new GroupMessage();
            groupMessage.setGroupid(groupid);
            groupMessage.setUserid(userid);
            groupMessage.setCreatetime(new Date());
            groupMessage.setMessage(textMessage);
            int insert = groupMessageService.insert(groupMessage);
            if(insert > 0){
                sendMessageAllByGroupid(JSON.toJSONString(map1), groupid);
            }
        } catch (Exception e) {
            log.info("发生了错误了");
        }
    }

    public void sendMessageTo(String message, int toUserid) throws IOException {
        for (WebSocket item : clients) {
            if (item.getUserid() == toUserid) {
                item.getSession().getAsyncRemote().sendText(message);
                break;
            }
        }
    }

    public void sendMessageAllByGroupid(String message, int groupid) throws IOException {
        for (WebSocket item : clients) {
            if (item.getGroupid() == groupid) {
                item.getSession().getAsyncRemote().sendText(message);
            }
        }
    }



    public int onlineNumber(int groupid) {
        int i = 0;
        for (WebSocket webSocket  : clients){
            if(webSocket.getGroupid() == groupid){
                i++;
            }
        }
        return i;
    }

    private List<String> getOnlineUserList(int groupid) {
        List<String> userList = new ArrayList<>();
        for (WebSocket webSocket  : clients){
            if(webSocket.getGroupid() == groupid){
                userList.add(userService.selectByPrimaryKey(webSocket.getUserid()).getUsername());
            }
        }
        return userList;
    }

}
